/*************************************************
 * ThinkJot V2
 * Author: Jeswin P. (jeswin@process64.com)
 * Website: http://www.process64.com/thinkjot/
 * This code is distributed under the terms of the
 * Apache License, Version 2.0.
 * **********************************************/
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using System.Threading;

namespace ThinkJot.Core.Blogs.Providers.Xml
{
    public class SerializationHelper
    {
        const int lockTimeOut = 100000; //100 seconds
        
        public void Serialize(object obj, string fileName)
        {
            Serialize(obj, fileName, "");
        }

        public void Serialize(object obj, string fileName, string namespaceURI)
        {
            ReaderWriterLock rwLock = SerializationManager.GetLock(fileName);
            rwLock.AcquireWriterLock(lockTimeOut); //Risky. Needs to be configurable!
            try
            {
                XmlSerializer serializer = new XmlSerializer(obj.GetType(), namespaceURI);
                using (FileStream fileStream = File.Open(fileName, FileMode.Create))
                {
                    if (fileStream != null)
                    {
                        serializer.Serialize(fileStream, obj);
                        
                        //Next time we will load from the disk
                        //Reason: If the serialize()^ fails to write to disk,
                        //  we will be sitting on an old copy of the object.
                        SerializationManager.RemoveObjectFromCache(fileName);
                        fileStream.Close();
                    }
                }
            }
            catch (Exception ex)
            {
                //Serializer Exceptions should go to the system log.
                new XmlLogger().LogSystemException(ex);
            }
            finally
            {
                rwLock.ReleaseWriterLock();
            }
        }

        public object Deserialize(string fileName, Type type)
        {
            return Deserialize(fileName, type, "");
        }

        public object Deserialize(string fileName, Type type, string namespaceURI)
        {
            object result = SerializationManager.GetObjectFromCache(fileName);
            if (result != null)
                return result;
            else
            {
                //Only infrequently requested objects will require a lock
                ReaderWriterLock rwLock = SerializationManager.GetLock(fileName);
                rwLock.AcquireReaderLock(lockTimeOut); //Risky. Needs to be configurable!
                try
                {
                    XmlSerializer serializer = new XmlSerializer(type, namespaceURI);
                    if (File.Exists(fileName))
                    {
                        using (FileStream fileStream = File.Open(fileName, FileMode.Open))
                        {
                            if (fileStream != null)
                            {
                                result = serializer.Deserialize(fileStream);
                                fileStream.Close();
                                SerializationManager.StoreInCache(fileName, result);
                                return result;
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    //Serializer Exceptions should go to the system log.
                    new XmlLogger().LogSystemException(ex);
                }
                finally
                {
                    rwLock.ReleaseReaderLock();                    
                }
                return null;
            }
        }
    }
}
